<!-- uniapp vue3 markdown解析 -->
<template>
    <view class="ua__markdown">
        <!-- <rich-text space="nbsp" :nodes="parseNodes(source)" @itemclick="handleLinkClick"></rich-text> -->
        <rich :content="parseNodes(source)" scrollTable @linkTap="linkTap" selectable></rich>
    </view>
</template>

<script setup>
import MarkdownIt from './lib/markdown-it.min.js';
import hljs from './lib/highlight/uni-highlight.min.js';
import './lib/highlight/atom-one-dark.css';
import rich from './lib/rich/rich.vue';

const props = defineProps({
    // 解析内容
    source: String,
    showLine: {
        type: [Boolean, String],
        default: true,
    },
});

let copyCodeData = [];
const markdown = MarkdownIt({
    html: true,
    highlight: function (str, lang) {
        let preCode = '';
        try {
            preCode = hljs.highlightAuto(str).value;
        } catch (err) {
            preCode = markdown.utils.escapeHtml(str);
        }
        const lines = preCode.split(/\n/).slice(0, -1);
        // 添加自定义行号
        let html = lines
            .map((item, index) => {
                if (item == '') {
                    return '';
                }
                return (
                    '<li><span class="line-num" data-line="' +
                    (index + 1) +
                    '"></span>' +
                    item +
                    '</li>'
                );
            })
            .join('');
        if (props.showLine) {
            html = '<ol style="padding: 0px 30px;">' + html + '</ol>';
        } else {
            html = '<ol style="padding: 0px 7px;list-style:none;">' + html + '</ol>';
        }
        copyCodeData.push(str);
        let htmlCode = `<div class="markdown-wrap">`;
        // #ifndef mp-weixin
        htmlCode += `<div style="color: #3478f5;text-align: right;font-size: 12px;padding:8px;font-weight:bold">`;
        htmlCode += `${lang}<a class="copy-btn" code-data-index="${
            copyCodeData.length - 1
        }" style="margin-left: 8px;">复制代码</a>`;
        htmlCode += `</div>`;
        // #endif
        htmlCode += `<pre class="hljs" style="padding:10px 8px;margin-bottom:5px;overflow: auto;display: block;border-radius: 5px;"><code>${html}</code></pre>`;
        htmlCode += '</div>';
        return htmlCode;
    },
});

const parseNodes = value => {
    if (!value) return;
    // 解析<br />到\n
    value = value.replace(/<br>|<br\/>|<br \/>/g, '\n');
    value = value.replace(/&nbsp;/g, ' ');
    let htmlString = '';
    if (value.split('```').length % 2) {
        let mdtext = value;
        if (mdtext[mdtext.length - 1] != '\n') {
            mdtext += '\n';
        }
        htmlString = markdown.render(mdtext);
    } else {
        htmlString = markdown.render(value);
    }
    // 解决小程序表格边框型失效问题
    htmlString = htmlString.replace(/<table/g, `<table class="table"`);
    htmlString = htmlString.replace(/<tr/g, `<tr class="tr"`);
    htmlString = htmlString.replace(/<th>/g, `<th class="th">`);
    htmlString = htmlString.replace(/<td/g, `<td class="td"`);
    htmlString = htmlString.replace(/<hr>|<hr\/>|<hr \/>/g, `<hr class="hr">`);

    return htmlString;
};

function linkTap(e) {
    const index = Number(e['code-data-index']);
    if (index >= 0) {
        uni.setClipboardData({
            data: copyCodeData[index],
            success: function () {
                uni.showToast({
                    title: '复制成功',
                    icon: 'success',
                });
            },
        });
    } else {
        uni.setClipboardData({
            data: e.href,
            success: function () {
                uni.showToast({
                    title: '已成功复制网址',
                    icon: 'success',
                });
            },
        });
    }
}
</script>

<style lang="scss" scoped>
.ua__markdown {
    line-height: 1.5;
    word-break: break-all;

    h1,
    h2,
    h3,
    h4,
    h5,
    h6 {
        font-family: inherit;
        font-weight: 500;
        line-height: 1.1;
        color: inherit;
    }

    h1,
    h2,
    h3 {
        margin-top: 20px;
        margin-bottom: 10px;
    }

    h4,
    h5,
    h6 {
        margin-top: 10px;
        margin-bottom: 10px;
    }

    .h1,
    h1 {
        font-size: 25px !important;
    }

    .h2,
    h2 {
        font-size: 20px !important;
    }

    .h3,
    h3 {
        font-size: 18px !important;
    }

    .h4,
    h4 {
        font-size: 16px !important;
    }

    .h5,
    h5 {
        font-size: 14px !important;
    }

    .h6,
    h6 {
        font-size: 12px !important;
    }

    a {
        background-color: transparent;
        color: #2196f3;
        text-decoration: none;
    }

    hr,
    ::v-deep .hr {
        margin-top: 20px;
        margin-bottom: 20px;
        border: 0;
        border-top: 1px solid #e5e5e5;
    }

    img {
        max-width: 35%;
    }

    p {
        margin: 0 0 10px;
    }

    em {
        font-style: italic;
        font-weight: inherit;
    }

    ol,
    ul {
        margin-top: 0;
        margin-bottom: 10px;
        padding-left: 40px;
    }

    ol ol,
    ol ul,
    ul ol,
    ul ul {
        margin-bottom: 0;
    }

    ol ol,
    ul ol {
        list-style-type: lower-roman;
    }

    ol ol ol,
    ul ul ol {
        list-style-type: lower-alpha;
    }

    dl {
        margin-top: 0;
        margin-bottom: 20px;
    }

    dt {
        font-weight: 600;
    }

    dt,
    dd {
        line-height: 1.4;
    }

    .task-list-item {
        list-style-type: none;
    }

    .task-list-item input {
        margin: 0 0.2em 0.25em -1.6em;
        vertical-align: middle;
    }

    pre {
        position: relative;
        z-index: 11;
    }

    code,
    kbd,
    pre,
    samp {
        font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
    }

    code:not(.hljs) {
        padding: 2px 4px;
        font-size: 90%;
        color: #c7254e;
        background-color: #ffe7ee;
        border-radius: 4px;
    }

    code:empty {
        display: none;
    }

    pre code.hljs {
        color: var(--vg__text-1);
        border-radius: 16px;
        background: var(--vg__bg-1);
        font-size: 12px;
    }

    .markdown-wrap {
        font-size: 12px;
        margin-bottom: 10px;
    }

    pre.code-block-wrapper {
        background: #2b2b2b;
        color: #f8f8f2;
        border-radius: 4px;
        overflow-x: auto;
        padding: 1em;
        position: relative;
    }

    pre.code-block-wrapper code {
        padding: auto;
        font-size: inherit;
        color: inherit;
        background-color: inherit;
        border-radius: 0;
    }

    .code-block-header__copy {
        font-size: 16px;
        margin-left: 5px;
    }

    abbr[data-original-title],
    abbr[title] {
        cursor: help;
        border-bottom: 1px dotted #777;
    }

    blockquote {
        padding: 10px 20px;
        margin: 0 0 20px;
        font-size: 17.5px;
        border-left: 5px solid #e5e5e5;
    }

    blockquote ol:last-child,
    blockquote p:last-child,
    blockquote ul:last-child {
        margin-bottom: 0;
    }

    blockquote .small,
    blockquote footer,
    blockquote small {
        display: block;
        font-size: 80%;
        line-height: 1.42857143;
        color: #777;
    }

    blockquote .small:before,
    blockquote footer:before,
    blockquote small:before {
        content: '\2014 \00A0';
    }

    .blockquote-reverse,
    blockquote.pull-right {
        padding-right: 15px;
        padding-left: 0;
        text-align: right;
        border-right: 5px solid #eee;
        border-left: 0;
    }

    .blockquote-reverse .small:before,
    .blockquote-reverse footer:before,
    .blockquote-reverse small:before,
    blockquote.pull-right .small:before,
    blockquote.pull-right footer:before,
    blockquote.pull-right small:before {
        content: '';
    }

    .blockquote-reverse .small:after,
    .blockquote-reverse footer:after,
    .blockquote-reverse small:after,
    blockquote.pull-right .small:after,
    blockquote.pull-right footer:after,
    blockquote.pull-right small:after {
        content: '\00A0 \2014';
    }

    .footnotes {
        -moz-column-count: 2;
        -webkit-column-count: 2;
        column-count: 2;
    }

    .footnotes-list {
        padding-left: 2em;
    }

    table,
    ::v-deep .table {
        border-spacing: 0;
        border-collapse: collapse;
        width: 100%;
        max-width: 65em;
        overflow: auto;
        margin-top: 0;
        margin-bottom: 16px;
    }

    table tr,
    ::v-deep .table .tr {
        border-top: 1px solid #e5e5e5;
    }

    table th,
    table td,
    ::v-deep .table .th,
    ::v-deep .table .td {
        padding: 6px 13px;
        border: 1px solid #e5e5e5;
    }

    table th,
    ::v-deep .table .th {
        font-weight: 600;
        background-color: #eee;
    }

    .hljs[class*='language-']:before {
        position: absolute;
        z-index: 3;
        top: 0.8em;
        right: 1em;
        font-size: 0.8em;
        color: #999;
    }

    .hljs[class~='language-js']:before {
        content: 'js';
    }

    .hljs[class~='language-ts']:before {
        content: 'ts';
    }

    .hljs[class~='language-html']:before {
        content: 'html';
    }

    .hljs[class~='language-md']:before {
        content: 'md';
    }

    .hljs[class~='language-vue']:before {
        content: 'vue';
    }

    .hljs[class~='language-css']:before {
        content: 'css';
    }

    .hljs[class~='language-sass']:before {
        content: 'sass';
    }

    .hljs[class~='language-scss']:before {
        content: 'scss';
    }

    .hljs[class~='language-less']:before {
        content: 'less';
    }

    .hljs[class~='language-stylus']:before {
        content: 'stylus';
    }

    .hljs[class~='language-go']:before {
        content: 'go';
    }

    .hljs[class~='language-java']:before {
        content: 'java';
    }

    .hljs[class~='language-c']:before {
        content: 'c';
    }

    .hljs[class~='language-sh']:before {
        content: 'sh';
    }

    .hljs[class~='language-yaml']:before {
        content: 'yaml';
    }

    .hljs[class~='language-py']:before {
        content: 'py';
    }

    .hljs[class~='language-docker']:before {
        content: 'docker';
    }

    .hljs[class~='language-dockerfile']:before {
        content: 'dockerfile';
    }

    .hljs[class~='language-makefile']:before {
        content: 'makefile';
    }

    .hljs[class~='language-javascript']:before {
        content: 'js';
    }

    .hljs[class~='language-typescript']:before {
        content: 'ts';
    }

    .hljs[class~='language-markup']:before {
        content: 'html';
    }

    .hljs[class~='language-markdown']:before {
        content: 'md';
    }

    .hljs[class~='language-json']:before {
        content: 'json';
    }

    .hljs[class~='language-ruby']:before {
        content: 'rb';
    }

    .hljs[class~='language-python']:before {
        content: 'py';
    }

    .hljs[class~='language-bash']:before {
        content: 'sh';
    }

    .hljs[class~='language-php']:before {
        content: 'php';
    }
}
</style>
